package com.dong.framework;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;


public class LubanDispatcherServlet extends HttpServlet {

    String projectPath = this.getClass().getResource("/").getPath();
    Map<String, Object> methodMap = new ConcurrentHashMap<String, Object>();


    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取浏览器传过来的uriI
        String uri = req.getRequestURI();
        System.out.println(uri);
        //判断map中是否存在这个uri
        Method method = (Method) methodMap.get(uri);
        if (method != null) {
            //获取方法中的形参
            Parameter[] parameters = method.getParameters();
            Object[] object = new Object[parameters.length];
            if (parameters != null) {
                for (int i = 0; i < parameters.length; i++) {
                    //判断形参上是否有@RequestParam注解
                    if (parameters[i].isAnnotationPresent(RequestParam.class)) {
                        object[i] = req.getParameter(parameters[i].getAnnotation(RequestParam.class).value());
                    } else{
                        //获取形参的名字
                        String name = parameters[i].getName();
                        //获取形参的类型
                        Class<?> type = parameters[i].getType();
                        //参数类型是否有HttpServletRequest类型
                        if (type.equals(HttpServletRequest.class)) {
                        object[i] = req;
                        //参数类型是否有HttpServletResponse类型
                    } else if (type.equals(HttpServletResponse.class)) {
                        object[i] = resp;
                        //参数类型是否有HttpSession类型
                    } else if (type.equals(HttpSession.class)) {
                        object[i] = req.getSession();
                        //参数类型是否有String类型
                    } else if (type.equals(String.class)) {
                        object[i] = req.getParameter(name);
                    } else {
                        //参数类型是否有对象类型
                        try {
                            Object instance = type.newInstance();
                            for (Field field : type.getDeclaredFields()) {
                                field.setAccessible(true);
                                String fieldName = field.getName();
                                if (field.getType().equals(Integer.class)) {
                                    String fname=req.getParameter(fieldName);
                                    if (fname!=null) {
                                        field.set(instance, Integer.valueOf(fname));
                                    }
                                } else {
                                    field.set(instance, req.getParameter(fieldName));
                                }
                            }
                            object[i] = instance;
                        } catch (InstantiationException e) {
                            e.printStackTrace();
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        }

                    }
                }
                }
                //获取到方法所对应的类
                Class<?> declaringClass = method.getDeclaringClass();
                try {
                    //反射调用类的方法
                    method.invoke(declaringClass.newInstance(), object);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            } else {
                resp.setStatus(404);
            }
        }


    @Override
    public void init(ServletConfig config) {
           //获取SpringMvc配置的xml
            String xmlPathLocal = config.getInitParameter("springMvc");
            //获取到配置文件的绝对路径
            String path = LubanDispatcherServlet.class.getClassLoader().getResource(xmlPathLocal).getPath();
            //dom4j解析配置文件
            Document parse = parse(path);
            //获取配置文件的beans节点
            Element rootElement = parse.getRootElement();
            //获取配置文件中的compentscan
            Element element = rootElement.element("compentscan");
            //通过pageckage为key找到value
            String packages = element.attribute("package").getValue();
            //找到扫描到的包的绝对路径
            String s = projectPath + packages;
            s=s.replace(".", "/");
             System.out.println(s);
            scanProjectByPath(s);
    }

    public void scanProjectByPath(String path1){
        File file=new File(path1);
        System.out.println(file);
         scanFile(file);
    }

    public void scanFile(File file){
        if(file.isDirectory()){
            for (File file1 : file.listFiles()) {
                scanFile(file1);
            }
        }else {
            String path = file.getPath();
            if(path.endsWith(".class")) {
                path = path.replace(new File(projectPath) + "\\", "");
                path = path.substring(0, path.lastIndexOf("."));
                path = path.replace("\\", ".");
                System.out.println(path);

                try {
                    Class<?> clazz = Class.forName(path);
                    //判断类上是否有@Controller注解
                    if (clazz.isAnnotationPresent(Controller.class)) {
                        //判断类上是否有@RequestMapping注解
                        String typeMapping = "";
                        if (clazz.isAnnotationPresent(RequestMapping.class)) {
                            RequestMapping annotation = clazz.getAnnotation(RequestMapping.class);
                            //获取@RequestMapping的value
                            typeMapping = annotation.value();
                        }
                        for (Method method : clazz.getMethods()) {
                            RequestMapping annotation = method.getAnnotation(RequestMapping.class);
                            //判断方法上面是否有@RequestMapping
                            if (annotation != null) {
                                String methodMapping = annotation.value();
                                //map的key存的是类上RequestMapping+方法上的RequestMapping,value存的是method对象
                                methodMap.put(typeMapping + methodMapping, method);
                            }
                        }
                    }

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        }


    public Document parse(String path){
        SAXReader saxReader=new SAXReader();
        try {
           return  saxReader.read(new File(path));
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        return null;
    }
    }
